// 为构造方法中的属性赋值：在声明构造方法时使用 this.propertyName
class MyColor {
  int red;
  int green;
  int blue;

  MyColor(this.red, this.green, this.blue);
  // MyColor({required this.red, required this.green, required this.blue});

  // 默认值
  // MyColor([this.red = 0, this.green = 0, this.blue = 0]);
  // or
  // MyColor({this.red = 0, this.green = 0, this.blue = 0});
}

final color = MyColor(80, 80, 128);

// 构造函数体执行之前进行一些初始化

// 有时，当你在实现构造函数时，您需要在构造函数体执行之前进行一些初始化。例如，final 修饰的字段必须在构造函数体执行之前赋值。在初始化列表中执行此操作，该列表位于构造函数的签名与其函数体之间：

// Point.fromJson(Map<String, num> json)
//     : x = json['x'],
//       y = json['y'] {
//   print('In Point.fromJson(): ($x, $y)');
// }

// 初始化列表也是放置断言的便利位置，它仅会在开发期间运行：

// NonNegativePoint(this.x, this.y)
//     : assert(x >= 0),
//       assert(y >= 0) {
//   print('I just made a NonNegativePoint: ($x, $y)');
// }

class FirstTwoLetters {
  final String letterOne;
  final String letterTwo;

  // Create a constructor with an initializer list here:
  FirstTwoLetters(String word)
      : this.letterOne = word.substring(0, 1),
        this.letterTwo = word.substring(1, 2),
        assert(word.length < 2) {
    print('文字长度小于2');
  }
}

// 命名构造方法，允许一个类具有多个构造方法

class Point {
  double x, y;

  Point(this.x, this.y);

  Point.origin()
      : x = 0,
        y = 0;
}

final myPoint = Point.origin();

class Color {
  int red;
  int green;
  int blue;

  Color(this.red, this.green, this.blue);

  // Create a named constructor called "Color.black" here:
  Color.black()
      : red = 0,
        green = 0,
        blue = 0;
}

// 工厂构造方法
// 工厂构造方法。它能够返回其子类甚至 null 对象。要创建一个工厂构造方法，请使用 factory 关键字
class Square extends Shape {}

class Circle extends Shape {}

class Shape {
  Shape();
  factory Shape.fromTypeName(String typeName) {
    if (typeName == 'square') return Square();
    if (typeName == 'circle') return Circle();

    print('I don\'t recognize $typeName');
    throw Error();
  }
}

final shape1 = Shape.fromTypeName("square");

class IntegerHolder {
  IntegerHolder();

  // Implement this factory constructor.
  factory IntegerHolder.fromList(List<int> list) {
    if (list.length == 1) return IntegerSingle(list[0]);
    if (list.length == 2) return IntegerDouble(list[0], list[1]);
    if (list.length == 3) return IntegerTriple(list[0], list[1], list[2]);

    print('unrecognize list length');
    throw Error();
  }
}

class IntegerSingle extends IntegerHolder {
  final int a;
  IntegerSingle(this.a);
}

class IntegerDouble extends IntegerHolder {
  final int a;
  final int b;
  IntegerDouble(this.a, this.b);
}

class IntegerTriple extends IntegerHolder {
  final int a;
  final int b;
  final int c;
  IntegerTriple(this.a, this.b, this.c);
}

// 重定向构造方法
// 有时一个构造方法仅仅用来重定向到该类的另一个构造方法。重定向方法没有主体，它在冒号（:）之后调用另一个构造方法。

class Automobile {
  String make;
  String model;
  int mpg;

  // The main constructor for this class.
  Automobile(this.make, this.model, this.mpg);

  // Delegates to the main constructor.
  Automobile.hybrid(String make, String model) : this(make, model, 60);

  // Delegates to a named constructor
  Automobile.fancyHybrid() : this.hybrid('Futurecar', 'Mark 2');
}

class Color2 {
  int red;
  int green;
  int blue;

  Color2(this.red, this.green, this.blue);
  Color2.black() : this(0, 0, 0);
}

// Const 构造方法
// 如果你的类生成的对象永远都不会更改，则可以让这些对象成为编译时常量。为此，请定义 const 构造方法并确保所有实例变量都是 final 的。

class ImmutablePoint {
  const ImmutablePoint(this.x, this.y);

  final int x;
  final int y;

  static const ImmutablePoint origin = ImmutablePoint(0, 0);
}

final ImmutablePoint immutablePoint1 = ImmutablePoint(2, 3);
final ImmutablePoint immutablePoint2 = ImmutablePoint.origin;

class Recipe {
  final List<String> ingredients;
  final int calories;
  final double milligramsOfSodium;
  const Recipe(this.ingredients, this.calories, this.milligramsOfSodium);
}

main(List<String> args) {
  print(shape1); // Instance of 'Square'
}
